﻿/*
Source adapted from: http://www.webappers.com/progressBar/
*/

Type.registerNamespace('AjaxControlToolkit');

AjaxControlToolkit.ProgressBehavior = function (element) {

    //  Properties    
    this._mode = null;
    this._speed = null;
    //  keep track of the current percentage.
    //  when the continuous animation is running,
    //  this value will be -1    
    this._value = null;
    this._animate = null;
    this._tooltipText = null;
    this._statusText = null;
    this._showStatusText = null;

    //  the DOM element whose background image
    //  contains the indicator image
    this._indicator = null;

    //  Members used by the continuous animation
    //  resizing secquence
    this._sequenceAnimation = null;
    //  manually change the percentage
    this._percentageAnimation = null;
    //  handle the animation started event
    this._percentAnimationStartedHandler = null;
    //  handle the animation ended event
    this._percentAnimationEndedHandler = null;
    //  handle the percent animation property changed event
    this._percentAnimationPropertyChangedHandler = null;

    //  Members used by the percentage animation
    //  not running
    this._isPercentQueueRunning = null;
    //  create the empty request queue
    this._percentQueue = null;
    //  the DOM element that contains the percent status message
    this._info = null;

    AjaxControlToolkit.ProgressBehavior.initializeBase(this, [element]);
}

AjaxControlToolkit.ProgressBehavior.prototype = {
    initialize: function () {
        AjaxControlToolkit.ProgressBehavior.callBaseMethod(this, 'initialize');

        //  get the DOM element that contains the indicator
        this._indicator = $get(this.get_id() + '_indicator');
        this._info = $get(this.get_id() + '_info');

        if (this.get_Mode() == AjaxControlToolkit.Mode.Manual) {

            if (this.get_Animate()) {
                this._percentQueue = new Array();
                this._isPercentQueueRunning = false;

                //  create the animation that is used to change the percentage values
                this._percentageAnimation = new $AA.LengthAnimation(this._indicator, null, 35, 'style', 'width', null, null, '%');
                //  attach
                this._percentAnimationEndedHandler = Function.createDelegate(this, this._onPercentAnimationEnd);
                this._percentageAnimation.add_ended(this._percentAnimationEndedHandler);
                //  attach
                this._percentAnimationStartedHandler = Function.createDelegate(this, this._onPercentAnimationStart);
                this._percentageAnimation.add_started(this._percentAnimationStartedHandler);
                //  attach
                this._percentAnimationPropertyChangedHandler = Function.createDelegate(this, this._onPercentAnimationPropertyChanged);
                this._percentageAnimation.add_propertyChanged(this._percentAnimationPropertyChangedHandler);
            }

            //  hide the status text if the user
            //  doesn't want it displayed
            if (!this._showStatusText) {
                this._info.style.display = 'none';
            }

            //  set the percentage
            this.set_percentage(this.get_Value());
        }

        if (this.get_Mode() == AjaxControlToolkit.Mode.Continuous) {
            //  create the resize animation
            var resizeAnimation = new $AA.LengthAnimation(this._indicator, 1, 50, 'style', 'width', 0, 100, '%');
            var noOpAnimation = new $AA.ScriptAction(null, .1, 25, '');
            //  setup the sequence
            this._sequenceAnimation = new $AA.SequenceAnimation(null, null, null, [resizeAnimation, noOpAnimation], -1);

            this._value = -1;
            this._info.style.display = 'none';
        }
    },

    dispose: function () {
        AjaxControlToolkit.ProgressBehavior.callBaseMethod(this, 'dispose');
    },

    show: function () {
        this.get_element().style.display = '';
    },

    hide: function () {
        this.get_element().style.display = 'none';
    },

    play: function () {
        if (this.get_Mode() == AjaxControlToolkit.Mode.Continuous) {
            //  kick off the animation        
            this._sequenceAnimation.play();
        }
    },

    stop: function () {
        if (this.get_Mode() == AjaxControlToolkit.Mode.Continuous) {
            //  kick off the animation        
            this._sequenceAnimation.stop();
        }
    },

    set_percentage: function (percentage) {
        if (this.get_Mode() == AjaxControlToolkit.Mode.Manual) {

            if (this.get_Animate()) {
                //  add the request to the queue
                this._percentQueue.push(percentage);

                //  if we are not already processing,
                //  start processing the queue
                if (!this._isPercentQueueRunning) {
                    this._processPercentQueue();
                }
            }
            else {
                //  no animation, just set the percentage
                this._updatePercentage(percentage);
            }
        }
    },

    _processPercentQueue: function () {
        //  if there are items in the queue start
        //  processing them
        if (this._percentQueue.length > 0) {
            //  update the status to running
            this._isPercentQueueRunning = true;

            var fromPercent = this._indicator.style.width == '' ? 0 : $common.parseUnit(this._indicator.style.width).size;
            //var fromPercent = this.get_Value();
            var toPercent = this._percentQueue[0];

            // define the new percentage
            if ((toPercent.toString().substring(0, 1) == "+") || (toPercent.toString().substring(0, 1) == "-")) {
                toPercent = fromPercent + parseInt(toPercent);
            }

            //  make sure we don't go above or below
            //  the 0 - 100 range
            if (toPercent < 0) {
                toPercent = 0;
            }
            if (toPercent > 100) {
                toPercent = 100;
            }

            //  keep the actual value in sync        
            this._percentQueue[0] = toPercent;

            //  determine how long the animation should run
            var speed = this.get_Speed() > 0 ? this.get_Speed() : parseFloat('0.' + Math.abs(fromPercent - toPercent));

            //  update the animation values
            this._percentageAnimation.set_duration(speed);
            this._percentageAnimation.set_startValue(fromPercent);
            this._percentageAnimation.set_endValue(toPercent);

            //  kick off the animation
            this._percentageAnimation.play();
        }
    },

    _onPercentAnimationStart: function () {
        //  add the updating class
        Sys.UI.DomElement.addCssClass(this.get_element(), 'updating');
    },

    _onPercentAnimationEnd: function () {
        //  remove the updating class
        Sys.UI.DomElement.removeCssClass(this.get_element(), 'updating');

        this._updatePercentage(this._percentQueue[0]);
        // remove the entry from the queue
        this._percentQueue.splice(0, 1);
        //  we are not running any more
        this._isPercentQueueRunning = false;
        //  process any other items in the queue
        this._processPercentQueue();
    },

    _onPercentAnimationPropertyChanged: function (sender, args) {
        if (args.get_propertyName() == 'percentComplete') {
            //  get the width of the element, thats the percentage
            var width = sender.get_target().style.width;
            if (width != '') {
                this._updatePercentage($common.parseUnit(width).size);
            }
        }
    },

    _updatePercentage: function (value) {
        this._value = parseInt(value);
        this._indicator.style.width = value + '%';

        //  apply the tooltip
        this._info.innerHTML = this._statusText ? String.format(this._statusText, value) : value + '%';
        this.get_element().title = this._tooltipText ? String.format(this._tooltipText, value) : value + '%';
    },

    get_Mode: function () {
        return this._mode;
    },
    set_Mode: function (value) {
        //  ToDo: can't set this property after the control has been initialized
        if (this._mode != value) {
            this._mode = value;
            this.raisePropertyChanged('Mode');
        }
    },

    get_Value: function () {
        return this._value;
    },
    set_Value: function (value) {
        //  ToDo: can't set this property after the control has been initialized
        if (this._value != value) {
            this._value = value;
            this.raisePropertyChanged('Value');
        }
    },

    get_Animate: function () {
        return this._animate;
    },
    set_Animate: function (value) {
        //  ToDo: can't set this property after the control has been initialized
        if (this._animate != value) {
            this._animate = value;
            this.raisePropertyChanged('Animate');
        }
    },

    get_Speed: function () {
        return this._speed;
    },
    set_Speed: function (value) {
        if (this._speed != value) {
            this._speed = value;
            this.raisePropertyChanged('Speed');
        }
    },

    get_ToolTip: function () {
        return this._tooltipText;
    },

    set_ToolTip: function (value) {
        if (this._tooltipText != value) {
            this._tooltipText = value;
            this.raisePropertyChanged('Tooltip');
        }
    },

    get_StatusText: function () {
        return this._statusText;
    },

    set_StatusText: function (value) {
        if (this._statusText != value) {
            this._statusText = value;
            this.raisePropertyChanged('StatusText');
        }
    },

    get_ShowStatusText: function () {
        return this._showStatusText;
    },

    set_ShowStatusText: function (value) {
        if (this._showStatusText != value) {
            this._showStatusText = value;
            this.raisePropertyChanged('ShowStatusText');
        }
    }
}
AjaxControlToolkit.ProgressBehavior.registerClass('AjaxControlToolkit.ProgressBehavior', Sys.UI.Control);

AjaxControlToolkit.Mode = function () {
    throw Error.invalidOperation();
}
AjaxControlToolkit.Mode.prototype = {
    Manual: 0,
    Continuous: 1
}
AjaxControlToolkit.Mode.registerEnum('AjaxControlToolkit.Mode');